#include "StdAfx.h"
#include "ViewSystem.h"


ViewSystem::ViewSystem():data(NULL),m_Mesh(NULL),m_MeshRepair(NULL)
{
	data = Database::getInstance();
}

bool ViewSystem::LoadModel( std::string fileName )
{
	//Load Mesh
	if(data)data->Destroy();
	data = Database::getInstance();
	if( data->mesh != NULL ){
		delete data->mesh ;
	}
	data->mesh = new Tri_Mesh;
	data->broken_edges.clear();
	data->group_broken_edges.clear();
	if( !ReadFile( fileName , data->mesh ) )
	{
		printf("Model load unsuccessfully\n");
		return false;
	}
	printf("Model load successfully\n");
	printf("Model vertices : %d\n",data->mesh->n_vertices());
	//set member value
	m_Mesh = data->mesh;
	if(m_MeshRepair!=NULL)
	{
		delete m_MeshRepair;
	}
	m_MeshRepair = new MeshRepair();
}

void ViewSystem::Render()
{
	RenderModel();
	RenderBrokenEdges();
}

void ViewSystem::RenderModel()
{
	if(m_Mesh!=NULL)
	{
		if( isRenderWireframe )
		{
			m_Mesh->Render_SolidWireframe();
		}
		else
		{
			m_Mesh->Render_Solid();
		}

		//Draw LS Points
		/*glEnable(GL_DEPTH_TEST);
		glPointSize(3.0f);
		glColor3f( 1.0, 0.0, 0.0 );
		glBegin(GL_POINTS);
		for each(OMT::Point p in data->solvedPoints)
		{
			glVertex3dv( p.data() );
		}
		glEnd();*/

		if(data->lsMesh2D!=NULL)
		{
			glDisable(GL_LIGHTING);
			glEnable(GL_POLYGON_OFFSET_FILL);
			glEnable(GL_DEPTH_TEST);
			glPolygonOffset(2.0, 2.0);
			if(isRenderWireframe)
			{
				/*glColor4f(0.6, 0.5, 0.49, 1.0);
				glBegin(GL_TRIANGLES);
				for (OMT::FIter f_it = data->lsMesh2D->faces_begin(); f_it != data->lsMesh2D->faces_end(); ++f_it) 
				{
					for (OMT::FVIter fv_it = data->lsMesh2D->fv_iter( f_it ); fv_it; ++fv_it)
					{						
						glVertex3dv(&data->lsMesh2D->point(fv_it.handle())[0]);
					}
				}
				glEnd();*/

				glLineWidth(0.02f);
				glColor3f(0.7, 0.2, 0.0);	
				glBegin(GL_LINES);
				for(OMT::EIter e_it = data->lsMesh2D->edges_begin(); e_it != data->lsMesh2D->edges_end(); ++e_it)
				{
					OMT::HEHandle _hedge = data->lsMesh2D->halfedge_handle(e_it.handle(),1);

					OMT::Point curVertex  = data->lsMesh2D->point(data->lsMesh2D->from_vertex_handle(_hedge));
					glVertex3dv(&curVertex[0]);
					curVertex = data->lsMesh2D->point(data->lsMesh2D->to_vertex_handle(_hedge));
					glVertex3dv(&curVertex[0]);			
				}
				glEnd();
			}
			else
			{
				glLineWidth(0.02f);
				glColor3f(1.0, 0.0, 0.0);	
				glBegin(GL_LINES);
				for(OMT::EIter e_it = data->lsMesh2D->edges_begin(); e_it != data->lsMesh2D->edges_end(); ++e_it)
				{
					OMT::HEHandle _hedge = data->lsMesh2D->halfedge_handle(e_it.handle(),1);

					OMT::Point curVertex  = data->lsMesh2D->point(data->lsMesh2D->from_vertex_handle(_hedge));
					glVertex3dv(&curVertex[0]);
					curVertex = data->lsMesh2D->point(data->lsMesh2D->to_vertex_handle(_hedge));
					glVertex3dv(&curVertex[0]);			
				}
				glEnd();
			}
			

			/*glPointSize(12.0f);
			glColor3f(0.0, 0.0, 0.7);	
			glBegin(GL_POINTS);
			for each(int idx in data->lsControlPointIdx)
			{
				OMT::VHandle vh = data->lsMesh2D->vertex_handle(idx);
				glVertex3dv( data->lsMesh2D->point(vh).data() );
			}

			glEnd();*/

			//glPopAttrib();
			glDisable(GL_POLYGON_OFFSET_FILL);
		}
		m_Mesh->Render_Select_VertexAndOneRing();
		m_Mesh->Render_Select_Faces();
		m_Mesh->Render_Select_Edge();
	}
}

void ViewSystem::RenderBrokenEdges()
{
	if(m_Mesh!=NULL && data->broken_edges.size()!=0)
	{
		glEnable(GL_DEPTH_TEST);
		glLineWidth(4.0);
		glColor3f(1.0, 0.0, 0.0);
		glBegin(GL_LINES);
		for each(OMT::HEHandle heh in data->broken_edges)
		{
			OMT::VHandle v1,v2;
			v1 = m_Mesh->to_vertex_handle(heh);
			v2 = m_Mesh->from_vertex_handle(heh);
			glVertex3dv(m_Mesh->point(v1).data());
			glVertex3dv(m_Mesh->point(v2).data());
			//m_Mesh->to_vertex_handle(eh);
		}
		glEnd();
		glDisable(GL_DEPTH_TEST);
	}
}

void ViewSystem::RenderGroupBrokenEdges( int idx )
{
	if(idx<0 || idx >= data->group_broken_edges.size() )
	{
		return ;
	}
	if(m_Mesh!=NULL)
	{
		glEnable(GL_DEPTH_TEST);
		glLineWidth(5.0);
		glColor3f(0.0, 1.0, 0.0);
		glBegin(GL_LINES);
		for each(OMT::HEHandle heh in data->group_broken_edges[idx])
		{
			OMT::VHandle v1,v2;
			v1 = m_Mesh->to_vertex_handle(heh);
			v2 = m_Mesh->from_vertex_handle(heh);
			glVertex3dv(m_Mesh->point(v1).data());
			glVertex3dv(m_Mesh->point(v2).data());
			//m_Mesh->to_vertex_handle(eh);
		}
		glEnd();
		glDisable(GL_DEPTH_TEST);
	}
}

void ViewSystem::RenderAllGroupBrokenEdges()
{
	if(m_Mesh!=NULL)
	{
		glLineWidth(5.0);
		glColor3f(0.0, 1.0, 0.0);
		glBegin(GL_LINES);
		for each(HEHs hehs in data->group_broken_edges)
		{
			for each(OMT::HEHandle heh in hehs)
			{
				OMT::VHandle v1,v2;
				v1 = m_Mesh->to_vertex_handle(heh);
				v2 = m_Mesh->from_vertex_handle(heh);
				glVertex3dv(m_Mesh->point(v1).data());
				glVertex3dv(m_Mesh->point(v2).data());
			}
		}
		glEnd();
	}
}

void ViewSystem::RenderGroupOneRing(int idx)
{
	if(idx<0 || idx >= data->group_broken_edges.size() )
	{
		return ;
	}
	glLineWidth(5.0);
	glColor3f(0.0, 1.0, 0.0);
	glBegin(GL_LINES);
	for each(OMT::HEHandle heh in data->group_broken_edges[idx])
	{
		OMT::VHandle v1,v2;
		v1 = m_Mesh->to_vertex_handle(heh);
		v2 = m_Mesh->from_vertex_handle(heh);
		glVertex3dv(m_Mesh->point(v1).data());
		glVertex3dv(m_Mesh->point(v2).data());
		//m_Mesh->to_vertex_handle(eh);
	}
	glColor3f(0.0, 0.2, 1.0);
	for each(OMT::HEHandle heh in data->group_broken_edges[idx])
	{
		OMT::VHandle v1,v2;
		v1 = m_Mesh->to_vertex_handle(heh);
		glVertex3dv(m_Mesh->point(v1).data());
		for(OMT::VVIter vv_it = m_Mesh->vv_iter(v1);vv_it;vv_it++)
		{
			v2 = vv_it.handle();
			glVertex3dv(m_Mesh->point(v2).data());
		}
	}
	glEnd();
}


void ViewSystem::MouseDown( const char* keyCode,int x,int y )
{
	if( strcmp(keyCode,"Left") == 0 )
	{
		if( m_Mesh!=NULL )m_Mesh->Select_Point( x, y );
	}
	else if( strcmp(keyCode,"Right") == 0 )
	{
		if( m_Mesh!=NULL )m_Mesh->Select_Point( x, y );
	}
}

void ViewSystem::MouseMove( const char* keyCode,int x,int y )
{
	
}
